package com.nycreativity.elecreativity.service.impl;

import com.alibaba.fastjson.JSONObject
import com.baomidou.mybatisplus.core.metadata.IPage
import com.baomidou.mybatisplus.core.toolkit.IdWorker
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.nycreativity.elecreativity.entity.dto.SkuSpecificationDTO
import com.nycreativity.elecreativity.entity.enums.IsDelEnum
import com.nycreativity.elecreativity.entity.param.sku.SkuAddParam
import com.nycreativity.elecreativity.entity.param.sku.SkuQueryParam
import com.nycreativity.elecreativity.entity.param.sku.SkuUpdateParam
import com.nycreativity.elecreativity.entity.po.Sku
import com.nycreativity.elecreativity.entity.vo.goods.SkuOfGoodsVO
import com.nycreativity.elecreativity.entity.vo.sku.SkuVO
import com.nycreativity.elecreativity.mapper.SkuMapper
import com.nycreativity.elecreativity.mapper.vomapper.SkuVOMapper
import com.nycreativity.elecreativity.service.SkuService
import com.nycreativity.elecreativity.util.COSUtil
import com.nycreativity.elecreativity.util.MappingUtil
import com.nycreativity.elecreativity.util.MultipartFileToFile
import com.nycreativity.elecreativity.util.usersession.UserContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.util.ObjectUtils
import org.springframework.web.multipart.MultipartFile
import java.time.LocalDateTime
import javax.annotation.Resource

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sxt && ttxxi
 * @since 2021-03-22
 */
@Service
class SkuServiceImpl : ServiceImpl<SkuMapper, Sku>(), SkuService {

    @Resource
    lateinit var skuMapper: SkuMapper

    @Resource
    lateinit var skuVOMapper: SkuVOMapper

    @Autowired
    lateinit var cosUtil: COSUtil

    @Transactional
    override fun addSku(files: Array<MultipartFile>, skuAddParam: SkuAddParam): Boolean {
        val sku = MappingUtil.getMappingObject(skuAddParam, Sku::class.java)
        //检测规格是否正确
        val skuSpecificationDTO = JSONObject.parseObject(sku.specification, SkuSpecificationDTO::class.java)
        if (skuSpecificationDTO == null || skuSpecificationDTO.isEmpty()) {
            log.error("规格参数不正确")
            return false
        }
        //查询是否已有该规格
        val checkExist = skuMapper.selectByGoodsIdAndSpecification(
            sku.goodsId!!,
            skuSpecificationDTO.size!!,
            skuSpecificationDTO.color!!
        )
        if (checkExist != null && checkExist.isNotEmpty()) {
            log.error("已存在同goodsId同规格sku")
            throw RuntimeException("已存在同goodsId同规格sku")
        }

        sku.id = IdWorker.getId()
        val imageList = uploadImage(sku.id!!, files)
        sku.images = imageList.joinToString(",")
        sku.creator = UserContext.get()?.id
        sku.createTime = LocalDateTime.now()
        skuMapper.insert(sku)
        return true
    }

    override fun queryPageByCondition(skuQueryParam: SkuQueryParam): IPage<SkuVO> {
        val page = Page<Any>(skuQueryParam.currentPage.toLong(), skuQueryParam.pageSize.toLong())
        return skuMapper.selectPageByCondition(page, skuQueryParam)
    }

    override fun queryByGoodsIdAndSpecification(goodsId: Long, skuSpecificationDTO: SkuSpecificationDTO): List<SkuVO>? {
        return skuMapper.selectByGoodsIdAndSpecification(goodsId, skuSpecificationDTO.size, skuSpecificationDTO.color)
    }

    override fun updateSpecificationByGoodsId(target: Int, goodsId: Long, oldOne: String, newOne: String) {
        when (target) {
            0 -> skuMapper.updateSizeByGoodsId(goodsId, oldOne, newOne)
            1 -> skuMapper.updateColorByGoodsId(goodsId, oldOne, newOne)
            else -> {
                log.error("target不合法")
                throw RuntimeException("target不合法")
            }
        }
    }

    override fun queryByGoodsId(goodsId: Long): List<SkuVO> {
        val queryWrapper = KtQueryWrapper(SkuVO::class.java)
        queryWrapper.eq(SkuVO::goodsId, goodsId).eq(SkuVO::isDel, IsDelEnum.NO.code)
        return skuVOMapper.selectList(queryWrapper)
    }

    override fun updateById(skuUpdateParam: SkuUpdateParam): Boolean {
        val sku = MappingUtil.getMappingObject(skuUpdateParam, Sku::class.java)
        if (sku == null || sku.isEmpty()) {
            return false
        }
        sku.modifier = UserContext.get()?.id
        sku.modifyTime = LocalDateTime.now()
        skuMapper.updateById(sku)
        return true
    }

    override fun deleteImage(skuId: Long, indexArray: IntArray) {
        val sku = skuMapper.selectById(skuId)
        val split = sku.images?.split(",")
        if (split == null || split.isEmpty()) {
            return
        }
        val imageList = ArrayList<String>()
        val deleteArray = ArrayList<String>()

        for (index in split.indices) {
            if (indexArray.contains(index)) {
                deleteArray.add(split[index])
            } else {
                imageList.add(split[index])
            }
        }
        //腾讯云上删除图片
        deleteArray.forEach {
            cosUtil.deleteFile(filePath = it)
        }

        //更新数据库
        sku.images = imageList.joinToString(",")
        sku.modifier = UserContext.get()?.id
        sku.modifyTime = LocalDateTime.now()
        skuMapper.updateById(sku)

    }

    override fun uploadImage(skuId: Long, files: Array<MultipartFile>): List<String> {
        val imageList = ArrayList<String>()
        val action: (MultipartFile) -> Unit = {
            val toFile = MultipartFileToFile.multipartFileToFile(it)
            val folder = getFolder(skuId)
            val fileName = getFileName(it)
            val putFile = cosUtil.putFile(file = toFile, folder = folder, fileName = fileName)
            //务必删除临时文件
            MultipartFileToFile.deleteTempFile(toFile)

            if (!putFile.first || ObjectUtils.isEmpty(putFile.third.toString())) {
                throw RuntimeException("文件上传腾讯云异常")
            }
            imageList.add(putFile.third.toString())
        }
        files.forEach(action)
        return imageList
    }

    override fun uploadNewImage(skuId: Long, files: Array<MultipartFile>): Boolean {
        val sku = skuMapper.selectById(skuId) ?: return false
        val imageList = uploadImage(skuId, files)
        if (sku.images == null || sku.images.equals("")) {
            sku.images = imageList.joinToString(",")
        } else {
            sku.images += "," + imageList.joinToString(",")
        }
        sku.modifier = UserContext.get()?.id
        sku.modifyTime = LocalDateTime.now()
        skuMapper.updateById(sku)
        return true
    }

    private fun getFolder(skuId: Long): String {
        return "ec/sku/$skuId"
    }

    private fun getFileName(multipartFile: MultipartFile): String {
        val originalFilename = multipartFile.originalFilename
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw RuntimeException("文件名为空，上传异常")
        }
        return System.currentTimeMillis().toString()
    }

    override fun deleteById(id: Long) {
        val wrapper = KtUpdateWrapper(Sku::class.java)
            .set(Sku::isDel, IsDelEnum.YES.code)
            .set(Sku::modifier, UserContext.get()?.id)
            .set(Sku::modifyTime, LocalDateTime.now())
            .eq(Sku::id, id)
        skuMapper.update(null, wrapper)
    }

    override fun queryGoodsSpecification(goodsId: Long): List<SkuOfGoodsVO> {
        return skuMapper.selectGoodsSpecification(goodsId)
    }

}